package SerialTest1;

import java.awt.event.*;

import javax.swing.*;
import javax.swing.event.*;
import javax.swing.plaf.FileChooserUI;
import java.awt.image.*;
import java.awt.*;
import java.util.*;
import java.io.*;
import java.lang.reflect.InvocationTargetException;

import javax.comm.*;

/**
 * Main file for SerialDemo program. This program illustrates many of the
 * abilities of the javax.comm api. This file contains the GUI framework that
 * the program runs in.
 */

public class SerialDemo extends Frame implements ActionListener {

	final int HEIGHT = 423;
	final int WIDTH = 610;

	public JPanel southPanel;

	public JButton openButton;
	public JButton closeButton;
	public JButton breakButton;
	public Panel buttonPanel;
	public JButton clearButton;

	public ConfigurationPanel configurationPanel;
	public SerialParameters parameters;
	public SerialConnection connection;
	public ListGUI lg;
	public Properties props = null;
	public ChatGUI cg;
	public static InputStream inputStream;
	

	/**
	 * Main method. Checks to see if the command line argument is requesting
	 * usage information (-h, -help), if it is, display a usage message and
	 * exit, otherwise create a new <code>SerialDemo</code> and set it visible.
	 */
	public static void main() {

		SerialDemo serialDemo = new SerialDemo();
		serialDemo.setVisible(true);
		serialDemo.repaint();
	}

	/**
	 * Create new <code>SerialDemo</code> and initializes it. Parses args to
	 * find configuration file. If found, initial state it set to parameters in
	 * configuration file.
	 * 
	 * @param args
	 *            command line arguments used when program was invoked.
	 * @return
	 */

	public SerialDemo() {
		super("Serial Demo");

		parameters = new SerialParameters();
		configurationPanel = new ConfigurationPanel(this);
		lg = new ListGUI();
		connection = new SerialConnection(this, parameters);

		buttonPanel = new Panel();
		buttonPanel.setLayout(new GridLayout(4, 1));
		openButton = new JButton("Open Port");
		openButton.addActionListener(this);
		buttonPanel.add(openButton);

		closeButton = new JButton("Close Port");
		closeButton.addActionListener(this);
		closeButton.setEnabled(false);
		buttonPanel.add(closeButton);

		breakButton = new JButton("Comm Start");
		breakButton.addActionListener(this);
		breakButton.setEnabled(false);
		buttonPanel.add(breakButton);

		clearButton = new JButton("Clear Field");
		clearButton.addActionListener(this);
		clearButton.setEnabled(false);
		buttonPanel.add(clearButton);

		GridBagLayout gridBag = new GridBagLayout();
		GridBagConstraints cons = new GridBagConstraints();

		southPanel = new JPanel();
		southPanel.setLayout(gridBag);

		cons.gridwidth = GridBagConstraints.REMAINDER;
		gridBag.setConstraints(configurationPanel, cons);
		cons.weightx = 1.0;
		southPanel.add(configurationPanel);
		gridBag.setConstraints(buttonPanel, cons);
		southPanel.add(buttonPanel);

		setConfigurationPanel();

	}

	// Thread-safe way to append to the chat box

	/**
	 * Sets the GUI elements on the configurationPanel.
	 */
	public void setConfigurationPanel() {
		configurationPanel.setConfigurationPanel();
	}

	/**
	 * Responds to the menu items and buttons.
	 */

	public void actionPerformed(ActionEvent e) {
		String cmd = e.getActionCommand();

		// Opens a port.
		if (cmd.equals("Open Port")) {
			openButton.setEnabled(false);
			clearButton.setEnabled(true);

			configurationPanel.setParameters();
			try {
				connection.openConnection();
			} catch (SerialConnectionException e2) {
				AlertDialog ad = new AlertDialog(this, "Error Opening Port!",
						"Error opening port,", e2.getMessage() + ".",
						"Select new settings, try again.");
				openButton.setEnabled(true);

				return;
			}
			portOpened();
		}

		// Closes a port.
		if (cmd.equals("Close Port")) {
			portClosed();
		}

		// Sends a break signal to the port.
		if (cmd.equals("Comm Start")) {
			connection.sendBreak();
		}

		// clear Field
		if (cmd.equals("Clear Field")) {

		}
	}

	/**
	 * Toggles the buttons to an open port state.
	 */
	public void portOpened() {
		openButton.setEnabled(false);
		closeButton.setEnabled(true);
		breakButton.setEnabled(true);
	}

	/**
	 * Calls closeConnection on the SerialConnection and toggles the buttons to
	 * a closed port state.
	 */
	public void portClosed() {
		connection.closeConnection();
		openButton.setEnabled(true);
		closeButton.setEnabled(false);
		breakButton.setEnabled(false);
	}

	/**
	 * Sets the <code>Cursor</code> for the application.
	 * 
	 * @param c
	 *            New <code>Cursor</code>
	 */

	/**
	 * Writes the current parameters to a configuration file of the
	 * java.properties style.
	 */

	/**
	 * Finds configuration file in arguments and creates a properties object
	 * from that file.
	 */

	/**
	 * Set the parameters object to the settings in the properties object.
	 */
	public void loadParams() {
		parameters.setPortName(props.getProperty("portName"));
		parameters.setBaudRate(props.getProperty("baudRate"));
		parameters.setFlowControlIn(props.getProperty("flowControlIn"));
		parameters.setFlowControlOut(props.getProperty("flowControlOut"));
		parameters.setParity(props.getProperty("parity"));
		parameters.setDatabits(props.getProperty("databits"));
		parameters.setStopbits(props.getProperty("stopbits"));

		setConfigurationPanel();
	}

	/**
	 * GUI element that holds the user changable elements for connection
	 * configuration.
	 */
	class ConfigurationPanel extends Panel implements ItemListener {

		public Frame parent;

		public Label portNameLabel;
		//public Choice portChoice;
		public TextField portChoice;
		
		public Label baudLabel;
		public Choice baudChoice;

		public Label flowControlInLabel;
		public Choice flowChoiceIn;

		public Label flowControlOutLabel;
		public Choice flowChoiceOut;

		public Label databitsLabel;
		public Choice databitsChoice;

		public Label stopbitsLabel;
		public Choice stopbitsChoice;

		public Label parityLabel;
		public Choice parityChoice;

		/**
		 * Creates and initializes the configuration panel. The initial settings
		 * are from the parameters object.
		 */
		public ConfigurationPanel(Frame parent) {
			this.parent = parent;

			setLayout(new GridLayout(8, 2));

			portNameLabel = new Label("Port Name:", Label.LEFT);
			add(portNameLabel);

			portChoice = new TextField();
			//portChoice.addActionListener(n);
			add(portChoice);
			listPortChoices();
			portChoice.setText(parameters.getPortName());

			baudLabel = new Label("Baud Rate:", Label.LEFT);
			add(baudLabel);

			baudChoice = new Choice();
			baudChoice.addItem("300");
			baudChoice.addItem("2400");
			baudChoice.addItem("9600");
			baudChoice.addItem("14400");
			baudChoice.addItem("28800");
			baudChoice.addItem("38400");
			baudChoice.addItem("57600");
			baudChoice.addItem("152000");
			baudChoice.select(Integer.toString(parameters.getBaudRate()));
			baudChoice.addItemListener(this);
			add(baudChoice);

			flowControlInLabel = new Label("Flow Control In:", Label.LEFT);
			add(flowControlInLabel);

			flowChoiceIn = new Choice();
			flowChoiceIn.addItem("None");
			flowChoiceIn.addItem("Xon/Xoff In");
			flowChoiceIn.addItem("RTS/CTS In");
			flowChoiceIn.select(parameters.getFlowControlInString());
			flowChoiceIn.addItemListener(this);
			add(flowChoiceIn);

			flowControlOutLabel = new Label("Flow Control Out:", Label.LEFT);
			add(flowControlOutLabel);

			flowChoiceOut = new Choice();
			flowChoiceOut.addItem("None");
			flowChoiceOut.addItem("Xon/Xoff Out");
			flowChoiceOut.addItem("RTS/CTS Out");
			flowChoiceOut.select(parameters.getFlowControlOutString());
			flowChoiceOut.addItemListener(this);
			add(flowChoiceOut);

			databitsLabel = new Label("Data Bits:", Label.LEFT);
			add(databitsLabel);

			databitsChoice = new Choice();
			databitsChoice.addItem("5");
			databitsChoice.addItem("6");
			databitsChoice.addItem("7");
			databitsChoice.addItem("8");
			databitsChoice.select(parameters.getDatabitsString());
			databitsChoice.addItemListener(this);
			add(databitsChoice);

			stopbitsLabel = new Label("Stop Bits:", Label.LEFT);
			add(stopbitsLabel);

			stopbitsChoice = new Choice();
			stopbitsChoice.addItem("1");
			stopbitsChoice.addItem("1.5");
			stopbitsChoice.addItem("2");
			stopbitsChoice.select(parameters.getStopbitsString());
			stopbitsChoice.addItemListener(this);
			add(stopbitsChoice);

			parityLabel = new Label("Parity:", Label.LEFT);
			add(parityLabel);

			parityChoice = new Choice();
			parityChoice.addItem("None");
			parityChoice.addItem("Even");
			parityChoice.addItem("Odd");
			parityChoice.select("None");
			parityChoice.select(parameters.getParityString());
			parityChoice.addItemListener(this);
			add(parityChoice);
		}

		/**
		 * Sets the configuration panel to the settings in the parameters
		 * object.
		 */
		public void setConfigurationPanel() {
			portChoice.setText(parameters.getPortName());
			baudChoice.select(parameters.getBaudRateString());
			flowChoiceIn.select(parameters.getFlowControlInString());
			flowChoiceOut.select(parameters.getFlowControlOutString());
			databitsChoice.select(parameters.getDatabitsString());
			stopbitsChoice.select(parameters.getStopbitsString());
			parityChoice.select(parameters.getParityString());
		}

		/**
		 * Sets the parameters object to the settings in the configuration
		 * panel.
		 */
		public void setParameters() {
			parameters.setPortName(portChoice.getText());
			parameters.setBaudRate(baudChoice.getSelectedItem());
			parameters.setFlowControlIn(flowChoiceIn.getSelectedItem());
			parameters.setFlowControlOut(flowChoiceOut.getSelectedItem());
			parameters.setDatabits(databitsChoice.getSelectedItem());
			parameters.setStopbits(stopbitsChoice.getSelectedItem());
			parameters.setParity(parityChoice.getSelectedItem());
		}

		/**
		 * Sets the elements for the portChoice from the ports available on the
		 * system. Uses an emuneration of comm ports returned by
		 * CommPortIdentifier.getPortIdentifiers(), then sets the current choice
		 * to a mathing element in the parameters object.
		 */
		void listPortChoices() {
			CommPortIdentifier portId;

			Enumeration en = CommPortIdentifier.getPortIdentifiers();

			// iterate through the ports.
			/*while (en.hasMoreElements()) {
				portId = (CommPortIdentifier) en.nextElement();
				if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
					portChoice.addItem(portId.getName());
				}
			}*/
			portChoice.setText(parameters.getPortName());
		}

		/**
		 * Event handler for changes in the current selection of the Choices. If
		 * a port is open the port can not be changed. If the choice is
		 * unsupported on the platform then the user will be notified and the
		 * settings will revert to their pre-selection state.
		 */
		public void itemStateChanged(ItemEvent e) {
			// Check if port is open.
			if (connection.isOpen()) {
				// If port is open do not allow port to change.
				if (e.getItemSelectable() == portChoice) {
					// Alert user.
					AlertDialog ad = new AlertDialog(parent, "Port Open!",
							"Port can not", "be changed",
							"while a port is open.");

					// Return configurationPanel to pre-choice settings.
					setConfigurationPanel();
					return;
				}
				// Set the parameters from the choice panel.
				setParameters();
				try {
					// Attempt to change the settings on an open port.
					connection.setConnectionParameters();
				} catch (SerialConnectionException ex) {
					// If setting can not be changed, alert user, return to
					// pre-choice settings.
					AlertDialog ad = new AlertDialog(parent,
							"Unsupported Configuration!",
							"Configuration Parameter unsupported,",
							"select new value.",
							"Returning to previous configuration.");
					setConfigurationPanel();
				}
			} else {
				// Since port is not open just set the parameter object.
				setParameters();
			}
		}
	}
}
/**
 * Handles closing down system. Allows application to be closed with window
 * close box.
 */

